﻿using NAudio.CoreAudioApi;
using NAudio.Wave;
using System.ComponentModel;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Test
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        AudioDeviceChangeNotifier audioDeviceChangeNotifier;

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public event PropertyChangedEventHandler? PropertyChanged;

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                audioDeviceChangeNotifier = new AudioDeviceChangeNotifier();
                audioDeviceChangeNotifier.DefaultDeviceChanged += AudioDeviceChangeNotifier_DefaultDeviceChanged;
            }
            catch { }

            Thread thTime = new Thread(new ThreadStart(GetTime));
            thTime.IsBackground = true;
            thTime.Start();

            StartWaveRecord();
        }

        private void AudioDeviceChangeNotifier_DefaultDeviceChanged(DataFlow dataFlow, Role deviceRole, string defaultDeviceId)
        {
            if (GetCurrentMicVolume() != MicStatus.OK)
            {
                return;
            }

            bool isRecordStart = StartWaveRecord();
        }

        WaveInProvider waveIn = null;
        private WaveInEvent waveSource = null;

        public static int wave_buffer_milliseconds = 600;
        public static int wave_buffer_collectbits = 16;
        public static int wave_buffer_collectchannels = 1;
        public static int wave_buffer_collectfrequency = 16000;
        private bool StartWaveRecord()
        {
            try
            {
                if (waveSource == null)
                {
                    waveSource = new WaveInEvent();
                    waveSource.BufferMilliseconds = wave_buffer_milliseconds;
                    waveSource.WaveFormat = new WaveFormat(wave_buffer_collectfrequency, wave_buffer_collectbits, wave_buffer_collectchannels); // 16bit,16KHz,Mono的录音格式
                    waveIn = new WaveInProvider(waveSource);
                    waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(WaveIn);
                    waveSource.RecordingStopped += WaveSource_RecordingStopped;
                    waveSource.StartRecording();
                }
                else
                {
                    waveSource.StartRecording();
                }
                return true;

            }
            catch (Exception e)
            {
                return false;
            }
        }

        private void WaveSource_RecordingStopped(object sender, StoppedEventArgs e)
        {
            try
            {
                if (e.Exception != null)
                {
                    waveSource.Dispose();
                    waveSource = null;
                    //waveIn = null;
                }

            }
            catch { }
        }

        private void WaveIn(object sender, WaveInEventArgs e)
        {
            if (e.Buffer != null && e.BytesRecorded > 0)
            {
                try
                {
                    waveIn.Read(e.Buffer, 0, e.BytesRecorded);
                }
                catch { }

            }
        }

        private MicStatus GetCurrentMicVolume()
        {
            MicStatus status = MicStatus.NotFound;
            int volume = -1;
            var enumerator = new MMDeviceEnumerator();

            IEnumerable<MMDevice> captureDevices = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToArray();
            if (captureDevices.Count() > 0)
            {
                MMDevice mMDevice = captureDevices.ToList()[0];
                if (mMDevice.AudioEndpointVolume.Mute)
                    return MicStatus.Mute;
                volume = (int)(mMDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100);
                if (volume == 0)
                {
                    status = MicStatus.ZeroOutput;
                }
                else if (volume == -1)
                {
                    status = MicStatus.NotFound;
                }
                else if (volume == -2)
                {
                    status = MicStatus.Mute;
                }
                else
                {
                    status = MicStatus.OK;
                }
            }
            return status;
        }

        private void GetTime()
        {
            while (true)
            {
                Thread.Sleep(10);
                Now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");

                App.Current.Dispatcher.Invoke(() =>
                {
                    Button_Click(null, null);
                });
            }
        }

        private void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        }

        private string now;

        public string Now
        {
            get { return now; }
            set { now = value; OnPropertyChanged(); }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var a = SqliteHelper.ExecuteDataset("SELECT * FROM Formula");
        }
    }

    public enum MicStatus
    {
        OK,
        Mute,
        ZeroOutput,
        NotFound
    }
}